﻿using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using UnityEditor.Animations;
using VRC.SDKBase.Editor;
using VRC.SDK3.Avatars.Components;
using VRC.SDKBase;
using System.Linq;
using System;
using UnityEngine.UIElements;

namespace AnimatorFix
{
    public class FixAnimationByPath : EditorWindow
    {
        // 选择的AnimatorController
        private AnimatorController selectedAnimatorController;
        // AnimatorController中的AnimationClips列表
        private List<AnimationClip> animationClips = new List<AnimationClip>();
        // 当前选中的AnimationClip索引
        private int selectedClipIndex = -1;
        // 当前选中的AnimationClip的Curve绑定信息
        private EditorCurveBinding[] currentBindings;
        // 当前选中的AnimationClip的原始绑定信息
        private EditorCurveBinding[] originalBindings;
        // 当前选中的AnimationClip的绑定对象
        private GameObject[] currentObjects;
        // 目标根对象
        private GameObject targetRoot;
        // 滚动条位置
        private Vector2 scrollPositionClips = Vector2.zero;
        private Vector2 scrollPositionBindings = Vector2.zero;
        // 分割布局的宽度
        private float splitterWidth = 200;
        // 是否显示无丢失的clips
        private bool showNonMissingClips = false;
        // 上一次选中的AnimatorController
        private AnimatorController lastSelectedAnimatorController = null;

        [MenuItem("工具/动画修复/Animator")]
        static void FixAnimationByPathMethod()
        {
            // 创建或获取窗口
            Rect wr = new Rect(0, 0, 800, 500);
            FixAnimationByPath window = (FixAnimationByPath)EditorWindow.GetWindowWithRect(typeof(FixAnimationByPath), wr, true, "动画修复工具");
            window.minSize = new Vector2(400, 300);
            window.Show();
        }

        void OnGUI()
        {
            // 使用水平布局
            using (var horizontalScope = new EditorGUILayout.HorizontalScope())
            {
                // 左侧：选择目标根对象和AnimatorController
                GUILayout.Space(10);
                using (var verticalScopeLeft = new EditorGUILayout.VerticalScope())
                {
                    // 选择目标根对象
                    using (var check = new EditorGUI.ChangeCheckScope())
                    {
                        EditorGUILayout.LabelField("目标根对象");
                        targetRoot = EditorGUILayout.ObjectField(targetRoot, typeof(GameObject), true) as GameObject;
                    }
                    if (targetRoot == null)
                    {
                        // 如果没有选择目标根对象，显示警告
                        EditorGUILayout.HelpBox("请先选择目标根对象", MessageType.Warning);
                        return;
                    }
                    // 选择是否显示无丢失的clips
                    showNonMissingClips = EditorGUILayout.Toggle("显示正常的Animation", showNonMissingClips);

                    // 选择AnimatorController
                    using (var check = new EditorGUI.ChangeCheckScope())
                    {
                        EditorGUILayout.LabelField("选择AnimatorController");
                        AnimatorController newAnimatorController = EditorGUILayout.ObjectField(selectedAnimatorController, typeof(AnimatorController), true) as AnimatorController;

                        if (check.changed || newAnimatorController != lastSelectedAnimatorController)
                        {
                            selectedAnimatorController = newAnimatorController;
                            lastSelectedAnimatorController = selectedAnimatorController;

                            if (selectedAnimatorController != null)
                            {
                                // 获取AnimatorController中的所有AnimationClip
                                animationClips = new List<AnimationClip>();
                                foreach (var clip in selectedAnimatorController.animationClips)
                                {
                                    // 检查是否为空的clip
                                    if (HasValidBindings(clip))
                                    {
                                        animationClips.Add(clip);
                                    }
                                }
                            }
                        }
                    }

                    // 显示AnimationClips列表
                    if (animationClips.Count > 0)
                    {
                        EditorGUILayout.LabelField("AnimationClips", EditorStyles.boldLabel);
                        using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPositionClips))
                        {
                            scrollPositionClips = scrollView.scrollPosition;
                            for (int i = 0; i < animationClips.Count; i++)
                            {
                                using (new EditorGUILayout.HorizontalScope())
                                {
                                    // 检查是否需要修复
                                    bool needsFix = CheckIfNeedsFix(animationClips[i], targetRoot);

                                    // 如果不显示无丢失的clips，并且当前clip不需要修复，则跳过
                                    if (!showNonMissingClips && !needsFix)
                                        continue;

                                    Color originalColor = GUI.color;
                                    if (needsFix)
                                    {
                                        GUI.color = Color.red;
                                    }

                                    // 显示AnimationClip名称
                                    if (GUILayout.Button(animationClips[i].name))
                                    {
                                        selectedClipIndex = i;
                                        LoadClipBindings(animationClips[i]);
                                    }

                                    GUI.color = originalColor;
                                }
                            }
                        }
                    }
                }

                // 分割线
                GUILayout.Space(10);

                // 右侧：显示选中AnimationClip的Curve绑定信息
                using (var verticalScopeRight = new EditorGUILayout.VerticalScope())
                {
                    // 显示选中AnimationClip的Curve绑定信息
                    if (selectedClipIndex >= 0 && selectedClipIndex < animationClips.Count)
                    {
                        AnimationClip selectedClip = animationClips[selectedClipIndex];

                        using (new EditorGUILayout.VerticalScope())
                        {
                            EditorGUILayout.LabelField($"当前选中: {selectedClip.name}", EditorStyles.boldLabel);

                            // 显示Curve绑定信息
                            if (currentBindings != null)
                            {
                                using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPositionBindings))
                                {
                                    scrollPositionBindings = scrollView.scrollPosition;
                                    for (int i = 0; i < currentBindings.Length; i++)
                                    {
                                        using (new EditorGUILayout.HorizontalScope())
                                        {
                                            // 显示绑定对象
                                            using var check0 = new EditorGUI.ChangeCheckScope();
                                            currentObjects[i] = EditorGUILayout.ObjectField(currentObjects[i], typeof(GameObject), true) as GameObject;
                                            if (check0.changed)
                                            {
                                                if (currentBindings[i] != null)
                                                    currentBindings[i].path = AnimationUtility.CalculateTransformPath(currentObjects[i].transform, targetRoot.transform);
                                            }

                                            // 显示并编辑绑定路径
                                            using var check = new EditorGUI.ChangeCheckScope();
                                            string newPath = EditorGUILayout.TextField(currentBindings[i].path);
                                            if (check.changed)
                                            {
                                                currentBindings[i].path = newPath;
                                                currentObjects[i] = GetBindingGameObject(currentBindings[i]);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        using (var hsr = new EditorGUILayout.HorizontalScope())
                        {
                            // 按照物体名字修复按钮
                            if (GUILayout.Button("按照物体名字修复"))
                            {
                                for (int i = 0; i < currentBindings.Length; i++)
                                {
                                    // 如果当前对象为空，则尝试根据名字修复
                                    if (currentObjects[i] == null)
                                    {
                                        string[] subPath = currentBindings[i].path.Split('/');
                                        if (subPath.Length > 0)
                                        {
                                            string name = subPath[subPath.Length - 1];
                                            currentObjects[i] = FindInChildren(targetRoot, name);
                                            if (currentBindings[i] != null && currentObjects[i] != null)
                                                currentBindings[i].path = AnimationUtility.CalculateTransformPath(currentObjects[i].transform, targetRoot.transform);
                                        }
                                    }
                                }
                            }
                            // 按照原来路径修复按钮
                            if (GUILayout.Button("按照原来路径修复"))
                            {
                                for (int i = 0; i < currentBindings.Length; i++)
                                {
                                    // 如果当前对象为空，则尝试路径名字修复
                                    if (currentObjects[i] == null)
                                    {
                                        currentObjects[i] = FindInChildren(targetRoot, currentBindings[i].path);
                                        if (currentBindings[i] != null && currentObjects[i] != null)
                                            currentBindings[i].path = AnimationUtility.CalculateTransformPath(currentObjects[i].transform, targetRoot.transform);
                                    }
                                }
                            }
                        }
                        using (var hsr = new EditorGUILayout.HorizontalScope())
                        {
                            // 重置按钮
                            if (GUILayout.Button("重置"))
                            {
                                LoadClipBindings(selectedClip);
                            }
                            // 保存按钮
                            if (GUILayout.Button("保存"))
                            {
                                SaveSelectedClip();
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 在子物体中查找指定名称的游戏对象
        /// </summary>
        /// <param name="obj">根对象</param>
        /// <param name="goName">要查找的游戏对象名称</param>
        /// <returns>找到的游戏对象，未找到则返回null</returns>
        private GameObject FindInChildren(GameObject obj, string goName)
        {
            Transform objTransform = obj.transform;
            Transform findedTransform = objTransform.Find(goName);

            GameObject finded;
            if (findedTransform == null)
            {
                for (int i = 0; i < objTransform.childCount; ++i)
                {
                    finded = FindInChildren(objTransform.GetChild(i).gameObject, goName);
                    if (finded)
                    {
                        return finded;
                    }
                }
                return null;
            }
            return findedTransform.gameObject;
        }

        /// <summary>
        /// 获取绑定的游戏对象
        /// </summary>
        /// <param name="binding">绑定信息</param>
        /// <returns>绑定的游戏对象，未找到则返回null</returns>
        private GameObject GetBindingGameObject(EditorCurveBinding binding)
        {
            UnityEngine.Object obj = AnimationUtility.GetAnimatedObject(targetRoot, binding);
            if (obj != null)
            {
                if (obj is GameObject)
                    return obj as GameObject;
                else if (obj is Transform)
                    return (obj as Transform).gameObject;
                else if (obj is Component)
                    return (obj as Component).gameObject;
                else
                {
                    Debug.Log("no found class");
                    return null;
                }
            }
            return null;
        }

        /// <summary>
        /// 检查AnimationClip是否为空的clip
        /// </summary>
        /// <param name="clip">AnimationClip</param>
        /// <returns>是否为空的clip</returns>
        private bool HasValidBindings(AnimationClip clip)
        {
            if (clip == null)
                return false;

            EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);
            return bindings.Length > 0;
        }

        /// <summary>
        /// 检查AnimationClip是否需要修复
        /// </summary>
        /// <param name="clip">AnimationClip</param>
        /// <param name="target">目标根对象</param>
        /// <returns>是否需要修复</returns>
        private bool CheckIfNeedsFix(AnimationClip clip, GameObject target)
        {
            if (clip == null || target == null)
                return false;

            EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(clip);
            foreach (var binding in bindings)
            {
                UnityEngine.Object obj = AnimationUtility.GetAnimatedObject(target, binding);
                if (obj == null)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 加载选中AnimationClip的绑定信息
        /// </summary>
        /// <param name="clip">AnimationClip</param>
        private void LoadClipBindings(AnimationClip clip)
        {
            if (clip == null || targetRoot == null)
                return;

            // 获取所有绑定信息，并排除掉binding.path为空的项
            EditorCurveBinding[] allBindings = AnimationUtility.GetCurveBindings(clip);
            currentBindings = allBindings.Where(binding => !string.IsNullOrEmpty(binding.path)).ToArray();
            originalBindings = currentBindings.ToArray();
            currentObjects = new GameObject[currentBindings.Length];

            for (int i = 0; i < currentBindings.Length; i++)
            {
                currentObjects[i] = GetBindingGameObject(currentBindings[i]);
            }
        }

        /// <summary>
        /// 保存选中的AnimationClip的绑定信息
        /// </summary>
        private void SaveSelectedClip()
        {
            if (selectedClipIndex < 0 || selectedClipIndex >= animationClips.Count)
                return;

            AnimationClip clip = animationClips[selectedClipIndex];
            if (clip == null || targetRoot == null)
                return;

            for (int i = 0; i < currentBindings.Length; i++)
            {
                if (currentObjects[i] == null)
                    continue;

                string newPath = AnimationUtility.CalculateTransformPath(currentObjects[i].transform, targetRoot.transform);
                AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, originalBindings[i]);

                AnimationUtility.SetEditorCurve(clip, originalBindings[i], null);
                currentBindings[i].path = newPath;
                AnimationUtility.SetEditorCurve(clip, currentBindings[i], curve);
            }

            // 更新AnimationClips列表
            animationClips[selectedClipIndex] = clip;
        }
    }
}